﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.IO;
using System.Linq;
using System.Net;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Json;
using System.Text;
using System.Web;
using DotNetOpenAuth.AspNet.Clients;

namespace SocialASP.Models
{
    [DataContract, EditorBrowsable(EditorBrowsableState.Never)]
    public class MyMicrosoftClientUserData : MicrosoftClientUserData
    {
        [DataMember(Name = "emails")]
        public Emails Emails { get; set; }
    }
    [DataContract, EditorBrowsable(EditorBrowsableState.Never)]
    public class Emails
    {
        [DataMember(Name = "preferred")]
        public string Preferred { get; set; }

        [DataMember(Name = "account")]
        public string Account { get; set; }

        [DataMember(Name = "personal")]
        public string Personal { get; set; }

        [DataMember(Name = "business")]
        public string Business { get; set; }
    }
    public class MyMicrosoftClient : MicrosoftClient
    {
        string appId;
        public MyMicrosoftClient(string appId, string appSecret)
            : base("microsoft", appId, appSecret)
        {
            this.appId = appId;
        }
        protected override Uri GetServiceLoginUrl(Uri returnUrl)
        {
            UriBuilder builder = new UriBuilder("https://oauth.live.com/authorize");
            Dictionary<string, string> dictionary = new Dictionary<string, string>();
            dictionary.Add("client_id", this.appId);
            dictionary.Add("scope", "wl.emails");
            dictionary.Add("response_type", "code");
            dictionary.Add("redirect_uri", returnUrl.AbsoluteUri);
            builder.AppendQueryArgs(dictionary);
            return builder.Uri;
        }

        protected override IDictionary<string, string> GetUserData(string accessToken)
        {
            MyMicrosoftClientUserData data;
            string url = "https://apis.live.net/v5.0/me?access_token=" + MyExtensions.EscapeUriDataStringRfc3986(accessToken);
            using (WebResponse response = WebRequest.Create(url).GetResponse())
            {
                using (Stream stream = response.GetResponseStream())
                {
                    data = Deserialize<MyMicrosoftClientUserData>(stream);
                }
            }
            Dictionary<string, string> dictionary = new Dictionary<string, string>();
            dictionary.Add("email", data.Emails.Account);
            dictionary.Add("id", data.Id);
            dictionary.Add("username", data.Name);
            dictionary.Add("name", data.Name);
            dictionary.Add("link", (data.Link == null) ? null : data.Link.AbsoluteUri);
            dictionary.Add("gender", data.Gender);
            dictionary.Add("firstname", data.FirstName);
            dictionary.Add("lastname", data.LastName);
            return dictionary;
        }

        public static T Deserialize<T>(Stream stream) where T : class
        {
            DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(T));
            return (T)serializer.ReadObject(stream);
        }

    }

    public static class MyExtensions
    {
        internal static void AppendQueryArgs(this UriBuilder builder, IEnumerable<KeyValuePair<string, string>> args)
        {
            if ((args != null) && (Enumerable.Count<KeyValuePair<string, string>>(args) > 0))
            {
                StringBuilder builder2 = new StringBuilder((int)(50 + (Enumerable.Count<KeyValuePair<string, string>>(args) * 10)));
                if (!string.IsNullOrEmpty(builder.Query))
                {
                    builder2.Append(builder.Query.Substring(1));
                    builder2.Append('&');
                }
                builder2.Append(CreateQueryString(args));
                builder.Query = (builder2.ToString());
            }
        }

        internal static string CreateQueryString(IEnumerable<KeyValuePair<string, string>> args)
        {
            if (!Enumerable.Any<KeyValuePair<string, string>>(args))
            {
                return string.Empty;
            }
            StringBuilder builder = new StringBuilder((int)(Enumerable.Count<KeyValuePair<string, string>>(args) * 10));
            foreach (KeyValuePair<string, string> pair in args)
            {
                builder.Append(EscapeUriDataStringRfc3986(pair.Key));
                builder.Append('=');
                builder.Append(EscapeUriDataStringRfc3986(pair.Value));
                builder.Append('&');
            }
            builder.Length = ((int)(builder.Length - 1));
            return builder.ToString();
        }

        private static readonly string[] UriRfc3986CharsToEscape = new string[] { "!", "*", "'", "(", ")" };

        internal static string EscapeUriDataStringRfc3986(string value)
        {
            StringBuilder builder = new StringBuilder(Uri.EscapeDataString(value));
            for (int i = 0; i < UriRfc3986CharsToEscape.Length; i = (int)(i + 1))
            {
                builder.Replace(UriRfc3986CharsToEscape[i], Uri.HexEscape(UriRfc3986CharsToEscape[i][0]));
            }
            return builder.ToString();
        }
    }
}